<template>
  <div v-if="data.controlTypeID != ''" class="OctopusAppControl">
    <!-- TODO:由iControl识别验证通过与否返回控制内部控件的样式为最简单的方式。 -->
    <div class="iControl"
         v-bind:class="(data.validate?'':'iError ')+(data.disabled?'iDisabled ':'')+('C_'+data.controlTypeID)">
      <!--  TODO: 利用下面的if判断控件类型，从而渲染不同的控件，vant针对特殊控件均进行了封装，需要在popup内部判断控件类型实现。-->
      <!--      {{data.controlTypeID}}-->
      <!-- 图像上传 | 文件上传 -->
      <template v-if="data.controlTypeID == 15 || data.controlTypeID == 16">
        <!--                {{modelValue}} <br>||<br> {{uploadFileList}}-->
        <div class="cell-name">{{data.displayName}}</div>
        <van-uploader :before-read="uploaderChange" :before-delete="uploaderBeforeRemove" @delete="uploaderRemove"
                      v-model="uploadFileList" :max-count="data.maxLength" multiple/>
      </template>
      <!-- 文本框 -->
      <template v-else-if="data.controlTypeID == 1">
        <!--        完整教程：https://m.w3cschool.cn/vantlesson/vantlesson-hoei35va.html-->
        <!--        <van-field v-model="modelValue" autosize show-word-limit v-on:input="change"-->
        <!--                   v-bind="{disabled:data.disabled || data.model != 'ITEM',type:'text',maxlength:data.maxLength,label:data.displayName}"/>-->
        <van-field v-model="modelValue" autosize v-on:input="change"
                   v-bind="{disabled:data.disabled || data.model != 'ITEM',type:'text',maxlength:data.maxLength,label:data.displayName}"/>
      </template>
      <!-- 多行文本框 -->
      <template v-else-if="data.controlTypeID == 2">
        <div>{{data.displayName}}</div>
        <van-field v-model="modelValue" rows="5" autosize show-word-limit v-on:input="change"
                   v-bind="{disabled:data.disabled || data.model != 'ITEM',type:'textarea',maxlength:data.maxLength}"/>
      </template>
      <!-- 数字框 | 小数点框 -->
      <template v-else-if="data.controlTypeID == 12 || data.controlTypeID == 13">
        <van-cell :title="data.displayName">
          <template slot="default" v-if="data.model == 'ITEM'">
            <van-stepper v-model="modelValue" :disabled="data.disabled" step="1"
                         :decimal-length="data.controlTypeID == 12 ? 0:2"
                         :min="data.minLength" :max="data.maxLength" input-width="80px" @change="change"/>
          </template>
          <template slot="default" v-else>
            {{modelValue}}
          </template>
        </van-cell>
      </template>
      <template v-else>
        <!-- {{modelValue}}||{{modelTemp}} -->
        <!--  van-cell 控件只能支持字符串输入，所以需要modelText来填充。-->
        <van-cell :title="data.displayName" :value="modelText?modelText:'请选择'" arrow-direction="down"
                  :is-link="!data.disabled && data.model == 'ITEM'"
                  v-on:click="select"/>
      </template>
    </div>

    <div class="iControlPopup">
      <van-popup v-model="showPopup" v-bind="{position:'bottom',class:'popup'}" v-on:close="selectByClose">
        <!-- 日历框 | 日历时间框 -->
        <template v-if="data.controlTypeID == 5 || data.controlTypeID == 6 || data.controlTypeID == 17">
          <van-datetime-picker v-model="modelTemp" :min-date="this.minDate" :max-date="this.maxDate"
                               v-bind="{type:data.controlTypeID=='5'?'date':data.controlTypeID=='6'?'datetime':'year-month'}"
                               @confirm="selectByDateConfirm" @cancel="selectByClose"/>
        </template>
        <template v-else>
          <div class="config">
            <van-row>
              <van-col span="10">
                <div class="cancel" @click="selectByClose">取消</div>
              </van-col>
              <van-col span="10">
                <div class="checkAll" @click="selectByListBoxCheckAll" v-if="data.controlTypeID == 11">全选/反选</div>
              </van-col>
              <van-col span="4">
                <div class="confirm" @click="selectByConfirm">确认</div>
              </van-col>
            </van-row>
          </div>
          <!-- 下拉框 -->
          <template v-if="data.controlTypeID == 3">
            <!--            {{modelTemp}}-->
            <van-radio-group class="bottomPopup" v-model="modelTemp">
              <van-cell-group>
                <van-cell v-for="(item, index) in requestData" :key="index" :title="item.label" clickable
                          @click="modelTemp = item.value;">
                  <van-radio slot="right-icon" :name="item.value"/>
                </van-cell>
              </van-cell-group>
            </van-radio-group>
          </template>
          <!-- 复选下拉框 -->
          <template v-else-if="data.controlTypeID == 11">
            <!-- {{modelTemp}} || {{modelValue}}-->
            <van-checkbox-group v-model="modelTemp" :max="data.maxLength">
              <van-cell v-for="(item, index) in requestData" clickable :key="index" :title="item.label"
                        @click="selectByListBoxCheck(index)">
                <van-checkbox :name="item.value" shape="square" ref="requestListBox" slot="right-icon"></van-checkbox>
              </van-cell>
            </van-checkbox-group>
          </template>
        </template>
      </van-popup>
    </div>
  </div>
  <div v-else>
    <label class="iLabel iError">Control Type Is Not Found</label>
  </div>
</template>

<script>
  export default {
    name: 'ControlEngine', /* 这个name暂时不知道用啥用，根据官方文档说的是方便排错的 */
    data() {
      return {
        octopus: this.$parent.octopus,
        // 这个属性待测试自定义model成功以后即可删除。
        dataExtend: null,
        // v-model模式必须使用value，这个是vue的保留字段，不能改名，内部已经通过prop属性传过来了。
        modelValue: this.value,
        modelText: "",
        modelTemp: null,


        showRequestPanel: false,// 查询面板是否展开。
        loading: false,
        requestData: [],

        showPopup: false, // 上传控件预览面板显示
        uploadFileList: [],
        uploadFileMaxSize: 4096 * 1000,  // 文件最大大小，目前是 4MB。

        // uploaderViewPath: '',   // 上传控件预览地址
        // uploadFileList: [],      // 上传控件文件清单列表
        // uploadFileMaxSize: 4096 * 1000,  // 文件最大大小，目前是 4MB。
      }
    },
    created: function () {
      this.init();
      this.octopus.tips.debug("Control.vue执行了created事件。");

    },
    // 当前控件挂载完成以后调用，因为ControlEngine每次进来都会触发Created事件，所以mounted也是能被触发的。
    mounted: function () {
      this.validate();
      this.bind();
      // console.log("data create:" + JSON.stringify(this.data));
      // 如果你希望整个同步DOM（不包含异步）都挂载完成，则需要写在nextTick事件中。
      this.$nextTick(function () {
        this.octopus.tips.debug("Control.vue执行了mounted.$nextTick事件。");
      });
      this.octopus.tips.debug("Control.vue执行了mounted事件。");
    },
    beforeUpdate: function () {
      this.octopus.tips.debug("Control.vue执行了beforeUpdate事件。");
    },
    updated: function () {
      // 基于VUE的特性，当控件发生变化则触发验证。
      this.validate();
      this.octopus.tips.debug("Control.vue执行了updated事件。");
    },
    // 活动事件，写在这里的好处是不管是第一次创建还是后退回来，都会触发这个事件
    // 比较典型的就是列表组件，返回的时候往往是需要刷新的。
    activated: function () {
      // this.$nextTick(function () {
      //   this.octopus.tips.debug("Control执行了activated.$nextTick事件。");
      // });
      this.octopus.tips.debug("Control.vue执行了activated事件。");
    },
    deactivated: function () {
      this.octopus.tips.debug("Control.vue执行了deactivated事件。");
    },
    computed: {
      // 如果cellData数据发生了改变,则触发这个事件。
      minDate() {
        let curDate = (new Date()).getTime();
        let one = 365 * 24 * 3600 * 1000 * this.data.maxLength;
        // 计算出最小值
        let oneYear = curDate - one;
        return new Date(oneYear);
      },
      maxDate() {
        let curDate = (new Date()).getTime();
        let one = 365 * 24 * 3600 * 1000 * this.data.minLength;
        let oneYear = curDate + one;
        return new Date(oneYear);
      },
    },
    methods: {
      init: function () {
        this.initData();
      },
      // 初始化数据
      initData: function () {
        // 记录变更，此处适配页面跳转进来，没有走监听的。
        this.dataExtend = $.extend(true, {}, this.data);
      },
      // 数据格式化及绑定，根据控件类型进行对应的数据修正，以及前端八爪鱼代码的解析，比如#{param=order}，则获取URL参数为orderID的值
      // 此处bind还会产生一个效果，就是原来vue的属性会自动隐藏掉。。。有点高级。。。。
      bind: function () {
        let o = this;
        let controlTypeID = this.data.controlTypeID;
        // 如果值不为空，则发起请求和处理。否则没有必要，直接显示【请选择】
        if (!this.octopus.tools.IsNullOrEmpty(this.modelValue)) {
          // 初始化控件各种形态的默认数据

          // 3：下拉框 4：复选框
          if (controlTypeID == "3" || controlTypeID == "11") {
            // 保存赋值确保统一。
            // alert(JSON.stringify(this.data));
            this.modelTemp = this.modelValue;
            // 此方法要加上回调，获取到数据以后填充modelText，但是不会去变更影响 modelValue 对象。
            this.request("", this.modelValue, function (data) {
              // 查询结果大于0才执行。
              if (data.length > 0) {
                // 单选框
                if (controlTypeID == "3") {
                  data = data[0];
                  o.modelText = data.label;
                }
                // 复选框
                else {
                  o.modelText = "";
                  $(data).each(function (index, item) {
                    o.modelText += ", " + item.label;
                  });
                  o.modelText = o.modelText.length > 1 ? o.modelText.substring(1) : "";
                }
              }
            });
          }
          // 日历控件 | 日历时间控件 Vant需要的是日期对象。
          else if (controlTypeID == "5" || controlTypeID == "6" || controlTypeID == "17") {
            // 初始化将日期字符串转成日期对象，由于赋值后日期会变成对象（vant要求），所以每次更新reload以后只能进来修改一次。
            // alert(typeof this.modelValue);
            if (typeof this.modelValue == "string") {
              // 日期格式化
              // this.modelValue = new Date(this.modelValue.replace(/-/g, '/'));
              this.modelValue = this.modelValue.replace(/-/g, '/');
              // 采用临时变量设置Vant控件
              this.modelTemp = new Date(this.modelValue);
              if (controlTypeID == "5") {
                this.modelText = this.octopus.tools.dateFormat(this.modelTemp, "yyyy-MM-dd");
              } else if (controlTypeID == "6") {
                this.modelText = this.octopus.tools.dateFormat(this.modelTemp, "yyyy-MM-dd HH:mm:ss");
              } else {
                this.modelText = this.octopus.tools.dateFormat(this.modelTemp, "yyyy-MM");
              }
            }
          }
          // 图像上传框 | 文件上传框
          else if (controlTypeID == "15" || controlTypeID == "16") {
            this.uploadFileList = JSON.parse(this.modelValue);
          }

        }
        // 如果值为空的情况下初始化设置。
        else {
          // 如果复选框为空，则需要设置[]
          if (controlTypeID == "11") {
            this.modelValue = [];
            this.modelTemp = this.modelValue;
            this.modelText = "";
          }
        }
      },
      // 完美解决自定义控件的问题！采用change曲线救国！！
      change: function (value) {
        // 触发绑定事件
        if (this.data.model == "LIST") {
          let key = (this.data.searchKey + "").toLocaleUpperCase();
          // 如果是范围查询，扩展searchValue的数据值为2个。
          if (key == "BETWEEN") {
            this.data.searchValue[this.index || 0] = value;
          }
          // 否则由控件组成的数组是直接返回的。
          else {
            this.data.searchValue = value;
          }

          this.octopus.tips.debug("[change]" + this.data.name + " 的 [searchValue] 发生了变更，由 "
            + JSON.stringify(this.dataExtend.searchValue) + " 变更为 " + JSON.stringify(this.data.searchValue));
        } else {
          this.data.defaultValue = value;

          this.octopus.tips.debug("[change]" + this.data.name + " 的 [defaultValue] 发生了变更，由 "
            + JSON.stringify(this.dataExtend.defaultValue) + " 变更为 " + JSON.stringify(this.data.defaultValue));
        }

        if (this.changed) {
          // 范围比较时需要判断0和1都需要有值
          if (this.data.searchKey == "BETWEEN") {
            // 只有当2个值不为空 或者 都为空 才触发。
            if ((!this.octopus.tools.IsNullOrEmpty(this.data.searchValue[0]) && !this.octopus.tools.IsNullOrEmpty(this.data.searchValue[1]))
              || (this.octopus.tools.IsNullOrEmpty(this.data.searchValue[0]) && this.octopus.tools.IsNullOrEmpty(this.data.searchValue[1]))) {
              this.changed(this.data, this.dataExtend);
            }
          } else {
            this.changed(this.data, this.dataExtend);
          }
        }
        this.dataExtend = $.extend(true, {}, this.data);

      },
      // 解码、格式化、验证 多步一体。
      validate: function () {
        let control = $(this.$el);
        // 状态默认开启
        let result = true;
        // 只有Item模式需要验证，List大多是下拉，模糊查询，所以没法做数据格式验证。
        if (this.data.model == "ITEM") {
          // 不允许非空，则判定。
          if (!this.data.null) {
            if (this.octopus.tools.IsNullOrEmpty(this.modelValue)) {
              result = false;
            } else {
              // 如果是图像上传
              if (this.data.controlTypeID == "15" || this.data.controlTypeID == "16") {
                if (JSON.parse(this.modelValue).length == 0) {
                  result = false;
                }
              }
            }
          }
          // 非空验证成功 并且 值不为空才进入，因为下面的验证都是针对数据的验证。
          if (result && !this.octopus.tools.IsNullOrEmpty(this.modelValue)) {
            // 数据格式化，日期取消，因为会触发一次change事件，没有意义，故放到后台处理
            // 日历框
            // if (this.data.controlTypeID == 5) {
            //   if (!this.octopus.tools.IsNullOrEmpty(this.data.defaultValue)) {
            //     this.data.defaultValue = this.octopus.tools.dateFormatToString(controlValue, "yyyy-MM-dd");
            //   }
            // }
            // // 日历时间框
            // else if (this.data.controlTypeID == 6) {
            //   if (!this.octopus.tools.IsNullOrEmpty(this.data.defaultValue)) {
            //     this.data.defaultValue = this.octopus.tools.dateFormatToString(controlValue, "yyyy-MM-dd HH:mm:ss");
            //   }
            // }
            // 邮件验证
            if (this.data.controlTypeID == 8) {
              let regex = /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/;
              result = regex.test(this.modelValue);
            }
            // 邮政编码框验证
            else if (this.data.controlTypeID == 9) {
              // 正则表达式，^开头，$结束，[\d]纯数字，{6}限制6位长度，范围可通过{6,10}。
              // http://tools.jb51.net/regex/create_reg
              let regex = /^[\d]{6}$/;
              // 查看匹配项
              // console.log(parseData.match(regex));
              // 查看
              result = regex.test(this.modelValue);
            }
            // 网址验证
            else if (this.data.controlTypeID == 10) {
              let regex = /^((https|http|ftp|rtsp|mms)?:\/\/)[^\s]+/;
              result = regex.test(this.modelValue);
            }
            // // 数字框
            // else if (this.data.controlTypeID == 12) {
            //   let regex = /^[\d]*$/;
            //   result = regex.test(this.modelValue);
            // }
            // // 小数点框（浮点）
            // else if (this.data.controlTypeID == 13) {
            //   let regex = /^[\d]*[.]{1}[\d]*$/;
            //   result = regex.test(this.modelValue);
            // }

            // 邮编框只能输入邮编
          }

        }
        // LIST模式下禁止验证禁用，默认false
        else {
          this.data.disabled = false;
        }

        this.data.validate = result;
      },
      select: function () {
        // 如果是禁用状态，则不弹出面板。
        if (!this.data.disabled && this.data.model == 'ITEM') {
          // 展开 popup 面板。
          this.showPopup = true;

          // 下拉框
          if (this.data.controlTypeID == "3") {
            // APP端的下拉框，将执行全部请求。
            this.request("", "");
            // 因为app控件使用了temp对象，所以此处bind的时候更新，需要string一下，否则前端传入int值会导致vant加载不上。
            this.modelTemp = this.modelValue ? this.modelValue.toString() : this.modelValue;
          }
          // 复选下拉框
          else if (this.data.controlTypeID == "11") {
            // APP端的复选框，将执行全部请求。
            this.request("", "");
            // 因为app控件使用了temp对象，所以此处bind的时候更新，需要[]一下，否则前端传入数组值会导致vant加载不上。
            this.modelTemp = this.modelValue ? this.modelValue : [];
            // alert(this.modelValue);
          }
        }
      },
      selectByDateConfirm: function (value) {
        this.modelValue = value;

        if (this.data.controlTypeID == "5") {
          this.modelText = this.octopus.tools.dateFormat(this.modelValue, "yyyy-MM-dd");
          this.modelValue = this.modelText;
        } else if (this.data.controlTypeID == "6") {
          this.modelText = this.octopus.tools.dateFormat(this.modelValue, "yyyy-MM-dd HH:mm:ss");
          this.modelValue = this.modelText;
        } else {
          this.modelText = this.octopus.tools.dateFormat(this.modelValue, "yyyy-MM");
          this.modelValue = this.modelText + "-1";
        }

        this.change(this.modelValue);
        this.selectByClose();
      },
      selectByListBoxCheck: function (index) {
        this.$refs.requestListBox[index].toggle();
      },
      // 选择全部
      selectByListBoxCheckAll: function () {
        let allList = [];
        this.requestData.forEach((item, index) => {
          allList.push(item.value);
        });

        //
        if (this.modelTemp.length == 0) {
          this.modelTemp = allList;
        } else {
          this.modelTemp = [];
        }
        // this.$refs.requestListBox[0].toggle();
      },
      selectByConfirm: function () {
        // 临时缓存变量正式赋值。
        this.modelValue = this.modelTemp;
        // console.log("））））" + this.modelTemp);
        // 发起变更请求
        this.change(this.modelValue);
        // 关闭面板
        this.selectByClose();
      },
      selectByClose: function () {
        // 恢复 临时缓存变量
        this.modelTemp = this.modelValue;
        // 关闭
        this.showPopup = false;
      },
      // 请求
      request: function (labelData, valueData, callback) {
        let o = this;
        this.loading = true;

        let control_request_celldata;
        // 自动化封装，文本：模糊；值：IN；为空：全部查询
        if (!this.octopus.tools.IsNullOrEmpty(labelData)) {
          control_request_celldata = [{
            name: this.data.controlSourceText, searchKey: "LIKE", searchValue: labelData
          }, {name: this.data.controlSourceValue}];
        } else if (!this.octopus.tools.IsNullOrEmpty(valueData)) {
          control_request_celldata = [{
            name: this.data.controlSourceText
          }, {name: this.data.controlSourceValue, searchKey: "IN", searchValue: valueData}];
        } else {
          control_request_celldata = [{
            name: this.data.controlSourceText
          }, {name: this.data.controlSourceValue}]
        }

        // 判断是否有关联数据，如果有则进行数据过滤。
        if (this.data.link) {
          // alert(JSON.stringify(this.data.link));
          $(this.data.link).each(function (index, item) {
            // 判断值是否存在，如果不存在，则设置为-1，保证查不到数据。
            item.value = o.octopus.tools.IsNullOrEmpty(item.value) ? -1 : item.value;
            // 得益于八抓鱼API框架，后台处理参数时，会自动识别 值 和 数组，所以这里直接赋值就可以了。
            control_request_celldata.push({name: item.mapping, searchKey: "IN", searchValue: item.value});
            // alert(JSON.stringify(control_request_celldata));
          });
          // alert(JSON.stringify(control_request_celldata));
        }

        // 请求后台八爪鱼API框架。
        this.octopus.request.api.post("/Octopus/Engine/List", {
            id: this.data.controlSourceID,
            // 当 data.model 不存在时，采用树状请求模式，存在值时，采用标准模式。
            parentKey: this.data.model == undefined ? this.data.controlSourceParentKey : null,
            parentValue: this.data.model == undefined ? this.data.controlSourceParentValue : null,
            orderData: this.data.controlSourceOrder,
            cellData: control_request_celldata,
            pageData: {rowSize: 1000}, // APP端，全部显示。
          },
          // 处理回调事件，通过分析data.status.code的状态来实现。
          function (result) {
            if (result.status.code == 200) {
              let requestTempData = []
              o.requestData = [];
              // o.$set(o, "requestData", []);
              // 回调封装数据
              $(result.content.queryData).each(function (index, item) {
                // 因为ElementUI识别数据类型，所以为了全适配，text和value必须都为String类型，否则会因为类型不正确匹配不上，切记。
                o.requestData.push({
                  label: item[o.data.controlSourceText],
                  // 因为Element-UI框架的问题，必须字符串，否则不能默认绑定。。。好傻。。所以要转换一下。
                  value: item[o.data.controlSourceValue] != null ? item[o.data.controlSourceValue].toString() : item[o.data.controlSourceValue],
                  // value: item[o.data.controlSourceValue].toString()
                });
              });

              if (callback) {
                callback(o.requestData);
              }
            } else {
              o.octopus.tips.error(result);
            }
            // 告诉控件，异步请求已经完成
            o.loading = false;
          });
      },
      // 上传事件
      uploaderChange: function (fileData) {
        let o = this;

        // 如果是单个文件
        if (fileData.length == undefined) {
          upload(fileData);
        }
        // 如果是多个文件
        else {
          if (fileData.length <= this.data.maxLength) {
            fileData.map(file => {
              upload(file);
            });
          } else {
            this.octopus.tips.error("超出上传限制，本控件只允许上传 " + this.data.maxLength + " 个文件。");
          }
        }

        // 正式上传函数
        function upload(file) {
          // 打印文件
          // console.error(file);

          // 如果大小在允许范围内，则进入，单位MB。
          if (file.size < o.data.height * 1024 * 1024) {
            o.octopus.request.api.upload(file,
              // 回调上传进度：百分比（引擎库已经自动计算，满分100分。）
              function (data) {
                // 移动端不考虑进度
              },
              // completed
              function (data) {
                if (data.status.code == 200) {
                  o.uploadFileList.push({
                    url: o.octopus.config.url + data.content.url,
                    name: data.content.name,
                    isImage: true
                  });
                  o.change(JSON.stringify(o.uploadFileList));
                }
              });
          } else {
            // 弹出提示
            o.octopus.tips.error("文件不能超过" + o.data.height + "MB，上传失败。");
            // 删除fileList
            o.uploadFileList = $.grep(o.uploadFileList, function (item) {
              return item.name != file.name;//筛选出当前数据列数据
            });
          }
        }

        // 不管成功与否，都终止，用于防止vant操作fileList。
        return false;
      },
      // 删除时触发
      uploaderRemove(file) {
        // console.log(file);
        // console.log(fileList);
        this.modelValue = JSON.stringify(this.uploadFileList);
        this.change(JSON.stringify(this.uploadFileList));
        this.octopus.tips.warning("移除了图像：" + file.name + "。");
      },
      uploaderBeforeRemove(file, fileList) {
        return this.$confirm(`确定移除图像： ${file.name}？`);
      },
    },
    watch: {
      // 监听value，因为有时候控件是二次绑定的，所以需要监听重新绑定，算是个vue的小缺陷吧。
      value(newv, oldv) {
        console.log("[change][watch]" + this.data.name + ":" + oldv + "==>" + newv);
        // 此处的更新和行：58 一致。
        this.modelValue = newv;
        // 记录变更，此处适配当前页弹出的，没有走created.init()的。
        this.dataExtend = $.extend(true, {}, this.data);

        // 如果值发生更改，且下拉框或者复选框，则需要重新绑定数据源。
        // 下拉框 和 复选框在变更时，需要同时清空 temp 和 text值。
        if (this.data.controlTypeID == "3" || this.data.controlTypeID == "11") {
          this.modelTemp = newv;
          this.modelText = "";
          // 如果值不为空 并且 查询面板是关闭状态，才有查询的意义，且还涉及到item和list控件的reload问题，因为reload以后，value必然为空。
          // if (!this.octopus.tools.IsNullOrEmpty(this.modelValue) && !this.showRequestPanel) {
          //   this.request("", this.modelValue);
          //   // 此处应该要调用方法改变modelText的值，重新绑定。
          // }
        }
        // 图像上传控件 || 文件上传控件
        else if (this.data.controlTypeID == "15" || this.data.controlTypeID == "16") {
          if (this.octopus.tools.IsNullOrEmpty(this.modelValue)) {
            this.uploadFileList = [];
          } else {
            this.uploadFileList = JSON.parse(this.modelValue);
          }
        }

        // 因为Vant控件是分离的，所以这里重新bind就行了。
        this.bind();
      },
      // // 针对一些妖孽的控件会在初创的生命周期时自动绑定值，此时change是感知不到的，需要这里反馈一下。
      // modelValue(newv, oldv) {
      //   // 仅适用于ITEM，List有bug，需要调整，估计也是因为这个原因，0无法清空。
      //   if (this.data.model == "ITEM") {
      //     if (this.modelValue != this.data.defaultValue) {
      //       this.change(this.modelValue);
      //     }
      //   }
      // }
    },
    // 此处value一定要加，虽然是vue的保留符。
    props: ["data", "index", "changed", "value"]
  }

</script>

<!--1	TextBox	文本框                  【支持】-->
<!--2	TextArea	多行文本框            【支持】-->
<!--3	DropDownList	异步下拉框        【用用户表测试】-->
<!--4	Label	标签框                    【支持】-->
<!--5	Calendar	日历框                【支持】-->
<!--6	CalendarTime	日历时间框        【支持】-->
<!--7	TreeList	树状下拉框            【用用户表测试】-->
<!--8	EmailBox	邮件框                【支持】-->
<!--9	ZipCodeBox	邮编框              【支持】-->
<!--10	HttpBox	网址框                【支持】-->
<!--11	MultipleDownList	异步多选框  【用用户表测试】-->
<!--12	IntegerBox	数字框            【支持】-->
<!--13	FloatBox	小数点框            【支持】-->
<!--14  IDCardBox 身份证框            【用用户表测试】-->
<!--手机号码框-->
<!--电话号码-->
<!--单选框、复选框待开发-->
